home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / dev / lang / Python151_Src.lha / Python1.5_Source / Modules / amigamodule.c < prev    next >
C/C++ Source or Header  |  1998-12-25  |  28KB  |  1,271 lines

  1. /**************************************************************\
  2. **                                                            **
  3. **  AMIGA module implementation, for SAS/C version 6.58       **
  4. **                                                            **
  5. **  Made by Irmen de Jong (irmen@bigfoot.com)                 **
  6. **                                                            **
  7. **  27-mar-96: Added a lot of AmiTCP functions!               **
  8. **   2-apr-96: Many small fixes & enhancements.               **
  9. **  11-apr-96: Totally rewritten the environment handling.    **
  10. **             Now creates 4 separate dictionaries.           **
  11. **             Fixed link(), added symlink() and readlink().  **
  12. **  29-may-96: Added filenote() and fullpath()                **
  13. **  11-jun-96: Moved filenote() to doslib/SetComment          **
  14. **  12-jun-96: Removed execv                                  **
  15. **  29-Aug-96: fixed getcwd(), some minor errno fixes         **
  16. **  26-Dec-96: upgraded to 1.4: added putenv(), remove()      **
  17. **             fixed mkdir: default protbits (0777)           **
  18. **   6-Apr-97: fixed bug in readlink (lock was incorrect)     **
  19. **   6-Nov-97: added uname()                                  **
  20. **  12-Jan-98: upgraded to 1.5: fixed includes, new names,    **
  21. **             uses new Amiga/.../unixemul.c                  **
  22. **  28-Mar-98: fixed buffer overflow bug in convertenviron()  **
  23. **  27-Sep-98: added crc32 function                           **
  24. **  24-Dec-98: moved bunch of #defines to config.h            **
  25. **  25-Dec-98: added I-Net 225 support                        **
  26. **                                                            **
  27. **  Adapted from posixmodule.c; implements as much of the     **
  28. **  functionality of this module as possible.                 **
  29. **                                                            **
  30. **                                                            **
  31. **  TO DO: Implement execv(e) and threads (if possible).      **
  32. **                                                            **
  33. **  NOTE: Don't forget __io2errno conversion!!!!!!!!!!!!!!!!  **
  34. **                                                            **
  35. \**************************************************************/
  36.  
  37.  
  38. #include "Python.h"
  39. #include "osdefs.h"
  40.  
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <errno.h>
  44. #include <stat.h>
  45. #ifndef INET225
  46. #include <dos.h>
  47. #endif
  48. #include <proto/dos.h>
  49. #include <proto/exec.h>
  50. #include <dos/dosextens.h>
  51. #include <dos/var.h>
  52. #include <dos/dostags.h>
  53. #include <exec/execbase.h>
  54.  
  55. #include "mytime.h"     /* For clock_t on some systems */
  56.  
  57. #ifdef HAVE_UTIME_H
  58. #include <utime.h>
  59. #endif
  60.  
  61. #include <dirent.h>
  62. #define NAMLEN(dirent) strlen((dirent)->d_name)
  63.  
  64. #ifdef AMITCP
  65. #include <clib/netlib_protos.h>
  66. #endif
  67.  
  68. #ifdef INET225
  69. #include <proto/socket.h>
  70. static int _OSERR;
  71. #define getegid() getgid()
  72. #define geteuid() getuid()
  73. static __inline int dup(int oldsd) { return s_dup(oldsd); }
  74. static __inline int dup2(int oldsd, int newsd) { return s_dup2(oldsd, newsd); }
  75. #endif
  76.  
  77. /* Return a dictionary corresponding to the AmigaDOS environment table. */
  78. /* That is, scan ENV: for global environment variables.                 */
  79. /* The local shell environment variables are put into another table.    */
  80.  
  81. static int
  82. convertenviron(PyObject **glob, PyObject **loc,
  83.                PyObject **both, PyObject **aliases)
  84. {
  85.     BPTR dlok;
  86.     struct FileInfoBlock __aligned fib;
  87.     PyObject *v;
  88.     char *dynbuf;
  89.     struct LocalVar *lvar;
  90.     struct List *localvars;
  91.  
  92.     *glob=PyDict_New();
  93.     *loc=PyDict_New();
  94.     *both=PyDict_New();
  95.     *aliases=PyDict_New();
  96.  
  97.     if(!*glob || !*loc || !*both || !*aliases)
  98.     {
  99.         if(*glob) Py_DECREF(*glob);
  100.         if(*loc) Py_DECREF(*loc);
  101.         if(*both) Py_DECREF(*both);
  102.         if(*aliases) Py_DECREF(*aliases);
  103.         return 0;
  104.     }
  105.  
  106.     /* Read global vars from ENV: */
  107.     /* Put them in 'glob' and in 'both'. */
  108.  
  109.     if(dlok=Lock("ENV:",ACCESS_READ))
  110.     {
  111.         if(Examine(dlok,&fib))
  112.         {
  113.             while(ExNext(dlok,&fib))
  114.             {
  115.                 if(fib.fib_DirEntryType<0)
  116.                 {
  117.                     if(dynbuf=malloc(fib.fib_Size+1))
  118.                     {
  119.                         int len=GetVar(fib.fib_FileName,dynbuf,fib.fib_Size+1,GVF_GLOBAL_ONLY);
  120.                         if(len>=0 && (v=PyString_FromString(dynbuf)))
  121.                         {
  122.                             PyDict_SetItemString(*glob,fib.fib_FileName,v);
  123.                             PyDict_SetItemString(*both,fib.fib_FileName,v);
  124.                             Py_DECREF(v);
  125.                         }
  126.                         free(dynbuf);
  127.                     }
  128.                 }
  129.             }
  130.         }
  131.     }
  132.  
  133.     if(dlok) UnLock(dlok);
  134.  
  135.     /* Scan the local shell environment, including "RC" and "Result2"!   */
  136.     /* Put shell vars in 'loc' and 'both', and aliases in 'aliases'. */
  137.     /* Because of the fact that the inserting of local vars into 'both' */
  138.     /* happens AFTER the insertion of global vars, the formor overwrite */
  139.     /* the latter, and thus have higher priority (as it should be). */
  140.  
  141.     localvars = (struct List*) &((struct Process*)FindTask(0))->pr_LocalVars;
  142.  
  143.     if(!IsListEmpty(localvars))
  144.     {
  145.         lvar = (struct LocalVar*) localvars->lh_Head;
  146.         do {
  147.             if(dynbuf=malloc(lvar->lv_Len+1))
  148.             {
  149.                 strncpy(dynbuf,lvar->lv_Value,lvar->lv_Len);
  150.                 dynbuf[lvar->lv_Len]=0;
  151.  
  152.                 if(v=PyString_FromString(dynbuf))
  153.                 {
  154.                     if(lvar->lv_Node.ln_Type==LV_VAR)
  155.                     {
  156.                         PyDict_SetItemString(*loc,lvar->lv_Node.ln_Name,v);
  157.                         PyDict_SetItemString(*both,lvar->lv_Node.ln_Name,v);
  158.                     }
  159.                     else if(lvar->lv_Node.ln_Type==LV_ALIAS)
  160.                         PyDict_SetItemString(*aliases,lvar->lv_Node.ln_Name,v);
  161.  
  162.                     Py_DECREF(v);
  163.                 }
  164.                 free(dynbuf);
  165.             }
  166.         } while((lvar=(struct LocalVar*)lvar->lv_Node.ln_Succ)->lv_Node.ln_Succ);
  167.     }
  168.  
  169.  
  170.     return 1;
  171. }
  172.  
  173.  
  174. static PyObject *AmigaError; /* Exception amiga.error */
  175.  
  176. /* Set a Amiga-specific error from errno, and return NULL */
  177.  
  178. static PyObject * amiga_error(void)
  179. {
  180.     return PyErr_SetFromErrno(AmigaError);
  181. }
  182.  
  183.  
  184. /* AMIGA generic methods */
  185.  
  186. static PyObject *
  187. amiga_1str(PyObject *args, int (*func)(const char *))
  188. {
  189.     char *path1;
  190.     int res;
  191.     if (!PyArg_Parse(args, "s", &path1))
  192.         return NULL;
  193.     Py_BEGIN_ALLOW_THREADS
  194.     res = (*func)(path1);
  195.     Py_END_ALLOW_THREADS
  196.     if (res < 0)
  197.         return amiga_error();
  198.     Py_INCREF(Py_None);
  199.     return Py_None;
  200. }
  201.  
  202. static PyObject *
  203. amiga_2str(PyObject *args, int (*func)(const char *, const char *))
  204. {
  205.     char *path1, *path2;
  206.     int res;
  207.     if (!PyArg_Parse(args, "(ss)", &path1, &path2))
  208.         return NULL;
  209.     Py_BEGIN_ALLOW_THREADS
  210.     res = (*func)(path1, path2);
  211.     Py_END_ALLOW_THREADS
  212.     if (res < 0)
  213.         return amiga_error();
  214.     Py_INCREF(Py_None);
  215.     return Py_None;
  216. }
  217.  
  218. static PyObject *
  219. amiga_strint(PyObject *args, int (*func)(const char *, int))
  220. {
  221.     char *path;
  222.     int i;
  223.     int res;
  224.     if (!PyArg_Parse(args, "(si)", &path, &i))
  225.         return NULL;
  226.     Py_BEGIN_ALLOW_THREADS
  227.     res = (*func)(path, i);
  228.     Py_END_ALLOW_THREADS
  229.     if (res < 0)
  230.         return amiga_error();
  231.     Py_INCREF(Py_None);
  232.     return Py_None;
  233. }
  234.  
  235. static PyObject *
  236. amiga_strintint(PyObject *args, int (*func)(const char *, int, int))
  237. {
  238.     char *path;
  239.     int i,i2;
  240.     int res;
  241.     if (!PyArg_Parse(args, "(sii)", &path, &i, &i2))
  242.         return NULL;
  243.     Py_BEGIN_ALLOW_THREADS
  244.     res = (*func)(path, i, i2);
  245.     Py_END_ALLOW_THREADS
  246.     if (res < 0)
  247.         return amiga_error();
  248.     Py_INCREF(Py_None);
  249.     return Py_None;
  250. }
  251.  
  252. static PyObject *
  253. amiga_do_stat(PyObject *self, PyObject *args, int (*statfunc)(const char *, struct stat *))
  254. {
  255.     struct stat st;
  256.     char *path;
  257.     int res;
  258.     if (!PyArg_Parse(args, "s", &path))
  259.         return NULL;
  260.     Py_BEGIN_ALLOW_THREADS
  261.     res = (*statfunc)(path, &st);
  262.     Py_END_ALLOW_THREADS
  263.     if (res != 0)
  264.         return amiga_error();
  265.     return Py_BuildValue("(llllllllll)",
  266.             (long)st.st_mode,
  267.             (long)st.st_ino,
  268.             (long)st.st_dev,
  269.             (long)st.st_nlink,
  270.             (long)st.st_uid,
  271.             (long)st.st_gid,
  272.             (long)st.st_size,
  273.             (long)st.st_atime,
  274.             (long)st.st_mtime,
  275.             (long)st.st_ctime);
  276. }
  277.  
  278.  
  279. /* AMIGA methods */
  280.  
  281. static PyObject *
  282. amiga_chdir(PyObject *self, PyObject *args)
  283. {
  284.     return amiga_1str(args, chdir);
  285. }
  286.  
  287. static PyObject *
  288. amiga_chmod(PyObject *self, PyObject *args)
  289. {
  290.     return amiga_strint(args, chmod);
  291. }
  292.  
  293. #ifdef HAVE_CHOWN
  294. static PyObject *
  295. amiga_chown(PyObject *self, PyObject *args)
  296. {
  297.     return amiga_strintint(args, chown);
  298. }
  299. #endif /* HAVE_CHOWN */
  300.  
  301. #ifdef HAVE_GETCWD
  302. static PyObject *
  303. amiga_getcwd(PyObject *self, PyObject *args)
  304. {
  305.     char buf[MAXPATHLEN];
  306.     char *res;
  307.     if (!PyArg_Parse(args,""))
  308.             return NULL;
  309.     Py_BEGIN_ALLOW_THREADS
  310.     res = getcwd(buf, sizeof buf);
  311.     Py_END_ALLOW_THREADS
  312.     if (res == NULL)
  313.             return amiga_error();
  314.     return PyString_FromString(buf);
  315. }
  316. #endif
  317.  
  318. #ifdef HAVE_LINK
  319. static PyObject *
  320. amiga_link(PyObject *self, PyObject *args)
  321. {
  322.     return amiga_2str(args, link);
  323. }
  324. #endif
  325.  
  326. static PyObject *
  327. amiga_listdir(PyObject *self, PyObject *args)
  328. {
  329.     BPTR dlok;
  330.     char *name;
  331.     struct FileInfoBlock __aligned fib;
  332.     PyObject *d;
  333.  
  334.     if (!PyArg_Parse(args, "s", &name)) return NULL;
  335.  
  336.     if ((d = PyList_New(0)) == NULL) return NULL;
  337.  
  338.     if(dlok=Lock(name,ACCESS_READ))
  339.     {
  340.         if(Examine(dlok,&fib))
  341.         {
  342.             while(ExNext(dlok,&fib))
  343.             {
  344.                 PyObject *v = PyString_FromString(fib.fib_FileName);
  345.                 if(v==NULL)
  346.                 {
  347.                     Py_DECREF(d); d=NULL; break;
  348.                 }
  349.  
  350.                 if(PyList_Append(d,v)!=0)
  351.                 {
  352.                     Py_DECREF(v); Py_DECREF(d); d=NULL; break;
  353.                 }
  354.                 Py_DECREF(v);
  355.             }
  356.         }
  357.         UnLock(dlok);
  358.     }
  359.  
  360.     if(IoErr()==ERROR_NO_MORE_ENTRIES) return d;
  361.  
  362.     Py_DECREF(d);
  363.     errno=__io2errno(_OSERR=IoErr());
  364.     return amiga_error();
  365. }
  366.  
  367. static PyObject *
  368. amiga_mkdir(PyObject *self, PyObject *args)
  369. {
  370.     int res;
  371.     char *path;
  372.     int mode = 0777;
  373.     if (!PyArg_ParseTuple(args, "s|i", &path, &mode)) return NULL;
  374.     Py_BEGIN_ALLOW_THREADS
  375. #ifdef INET225
  376.     res = mkdir(path, mode);
  377. #else
  378.     res = my_mkdir(path, mode);
  379. #endif
  380.     Py_END_ALLOW_THREADS
  381.     if (res < 0) return amiga_error();
  382.     Py_INCREF(Py_None); return Py_None;
  383. }
  384.  
  385. static PyObject *
  386. amiga_rename(PyObject *self, PyObject *args)
  387. {
  388.     return amiga_2str(args, rename);
  389. }
  390.  
  391. static PyObject *
  392. amiga_rmdir(PyObject *self, PyObject *args)
  393. {
  394.     return amiga_1str(args, rmdir);
  395. }
  396.  
  397. static PyObject *
  398. amiga_stat(PyObject *self, PyObject *args)
  399. {
  400.     return amiga_do_stat(self, args, stat);
  401. }
  402.  
  403. #ifdef HAVE_SYSTEM
  404. static PyObject *
  405. amiga_system(PyObject *self, PyObject *args)
  406. {
  407.     char *command;
  408.     long sts;
  409.     if (!PyArg_Parse(args, "s", &command))
  410.         return NULL;
  411.     Py_BEGIN_ALLOW_THREADS
  412.     sts = system(command);
  413.     Py_END_ALLOW_THREADS
  414.     return PyInt_FromLong(sts);
  415. }
  416. #endif
  417.  
  418. #if defined(AMITCP) || defined(INET225)
  419. static PyObject *
  420. amiga_umask(PyObject *self, PyObject *args)
  421. {
  422.     int i;
  423. #ifdef AMITCP
  424.     if (!checkusergrouplib()) return NULL;
  425. #else
  426.     if (!checksocketlib()) return NULL;
  427. #endif
  428.     if (!PyArg_Parse(args,"i",&i))
  429.         return NULL;
  430.     i = umask(i);
  431.     if (i < 0)
  432.         return amiga_error();
  433.     return PyInt_FromLong((long)i);
  434. }
  435. #endif
  436.  
  437. #ifdef HAVE_UNAME
  438. static PyObject *
  439. amiga_uname(PyObject *self, PyObject *args)
  440. {
  441.         struct utsname u;
  442.         int res;
  443.         if (!PyArg_NoArgs(args))
  444.                 return NULL;
  445.         Py_BEGIN_ALLOW_THREADS
  446.         res = uname(&u);
  447.         Py_END_ALLOW_THREADS
  448.         if (res < 0)
  449.                 return amiga_error();
  450.         return Py_BuildValue("(sssss)",
  451.                              u.sysname,
  452.                              u.nodename,
  453.                              u.release,
  454.                              u.version,
  455.                              u.machine);
  456. }
  457. #endif
  458.  
  459. static PyObject *
  460. amiga_unlink(PyObject *self, PyObject *args)
  461. {
  462.     return amiga_1str(args, unlink);
  463. }
  464.  
  465. #if defined(AMITCP) || defined(INET225)
  466. static PyObject *
  467. amiga_utime(PyObject *self, PyObject *args)
  468. {
  469.     char *path;
  470.     long atime, mtime;
  471.     int res;
  472.  
  473. #ifdef HAVE_UTIME_H
  474.     struct utimbuf buf;
  475. #define ATIME buf.actime
  476. #define MTIME buf.modtime
  477. #define UTIME_ARG &buf
  478. #else /* HAVE_UTIME_H */
  479.     time_t buf[2];
  480. #define ATIME buf[0]
  481. #define MTIME buf[1]
  482. #define UTIME_ARG buf
  483. #endif /* HAVE_UTIME_H */
  484.  
  485.     if (!PyArg_Parse(args, "(s(ll))", &path, &atime, &mtime))
  486.         return NULL;
  487.     ATIME = atime;
  488.     MTIME = mtime;
  489.     Py_BEGIN_ALLOW_THREADS
  490.     res = utime(path, UTIME_ARG);
  491.     Py_END_ALLOW_THREADS
  492.     if (res < 0)
  493.         return amiga_error();
  494.     Py_INCREF(Py_None);
  495.     return Py_None;
  496. #undef UTIME_ARG
  497. #undef ATIME
  498. #undef MTIME
  499. }
  500. #endif
  501.  
  502.  
  503. /* Process operations */
  504.  
  505. /* XXX Removed _exit. You are VERY STUPID if you used this. (2-apr-96) */
  506.  
  507. /* XXX Removed execv. You must use system/exit combination instead. */
  508. /*     Maybe one day I'll implement a REAL execv ?? */
  509.  
  510.  
  511.  
  512. #ifdef HAVE_GETEGID
  513. static PyObject *
  514. amiga_getegid(PyObject *self, PyObject *args)
  515. {
  516. #ifdef AMITCP
  517.     if (!checkusergrouplib()) return NULL;
  518. #else
  519.     if (!checksocketlib()) return NULL;
  520. #endif
  521.     if (!PyArg_Parse(args,""))
  522.         return NULL;
  523.     return PyInt_FromLong((long)getegid());
  524. }
  525. #endif
  526.  
  527. #ifdef HAVE_GETEUID
  528. static PyObject *
  529. amiga_geteuid(PyObject *self, PyObject *args)
  530. {
  531. #ifdef AMITCP
  532.     if (!checkusergrouplib()) return NULL;
  533. #else
  534.     if (!checksocketlib()) return NULL;
  535. #endif
  536.     if (!PyArg_Parse(args,""))
  537.         return NULL;
  538.     return PyInt_FromLong((long)geteuid());
  539. }
  540. #endif
  541.  
  542. #ifdef HAVE_GETGID
  543. static PyObject *
  544. amiga_getgid(PyObject *self, PyObject *args)
  545. {
  546. #ifdef AMITCP
  547.     if (!checkusergrouplib()) return NULL;
  548. #else
  549.     if (!checksocketlib()) return NULL;
  550. #endif
  551.     if (!PyArg_Parse(args,""))
  552.         return NULL;
  553.     return PyInt_FromLong((long)getgid());
  554. }
  555. #endif
  556.  
  557. static PyObject *
  558. amiga_getpid(PyObject *self, PyObject *args)
  559. {
  560.     if (!PyArg_Parse(args,""))
  561.         return NULL;
  562.     return PyInt_FromLong((long)FindTask(0));
  563. }
  564.  
  565. #ifdef HAVE_GETPGRP
  566. static PyObject *
  567. amiga_getpgrp(PyObject *self, PyObject *args)
  568. {
  569. #ifdef AMITCP
  570.     if (!checkusergrouplib()) return NULL;
  571. #else
  572.     if (!checksocketlib()) return NULL;
  573. #endif
  574.     if (!PyArg_Parse(args,""))
  575.         return NULL;
  576. #ifdef GETPGRP_HAVE_ARG
  577.     return PyInt_FromLong((long)getpgrp(0));
  578. #else /* GETPGRP_HAVE_ARG */
  579.     return PyInt_FromLong((long)getpgrp());
  580. #endif /* GETPGRP_HAVE_ARG */
  581. }
  582. #endif /* HAVE_GETPGRP */
  583.  
  584. #ifdef HAVE_SETPGRP
  585. static PyObject *
  586. amiga_setpgrp(PyObject *self, PyObject *args)
  587. {
  588. #ifdef AMITCP
  589.     if (!checkusergrouplib()) return NULL;
  590. #else
  591.     if (!checksocketlib()) return NULL;
  592. #endif
  593.     if (!PyArg_Parse(args,""))
  594.         return NULL;
  595. #ifdef SETPGRP_HAVE_ARG
  596.     if (setpgrp(0, 0) < 0)
  597. #else /* SETPGRP_HAVE_ARG */
  598.     if (setpgrp() < 0)
  599. #endif /* SETPGRP_HAVE_ARG */
  600.         return amiga_error();
  601.     Py_INCREF(Py_None);
  602.     return Py_None;
  603. }
  604.  
  605. #endif /* HAVE_SETPGRP */
  606.  
  607. #ifdef HAVE_GETPPID
  608. static PyObject *
  609. amiga_getppid(PyObject *self, PyObject *args)
  610. {
  611.     if (!PyArg_Parse(args,""))
  612.         return NULL;
  613.     return PyInt_FromLong((long)getppid());
  614. }
  615. #endif
  616.  
  617. #ifdef HAVE_GETUID
  618. static PyObject *
  619. amiga_getuid(PyObject *self, PyObject *args)
  620. {
  621. #ifdef AMITCP
  622.     if (!checkusergrouplib()) return NULL;
  623. #else
  624.     if (!checksocketlib()) return NULL;
  625. #endif
  626.     if (!PyArg_Parse(args,""))
  627.         return NULL;
  628.     return PyInt_FromLong((long)getuid());
  629. }
  630. #endif
  631.  
  632. #ifdef HAVE_POPEN
  633. static PyObject *
  634. amiga_popen(PyObject *self, PyObject *args)
  635. {
  636.     char *name;
  637.     char *mode = "r";
  638.     int bufsize = -1;
  639.     FILE *fp;
  640.     PyObject *f;
  641.     if (!PyArg_ParseTuple(args, "s|si", &name, &mode, &bufsize))
  642.         return NULL;
  643.     Py_BEGIN_ALLOW_THREADS
  644.     fp = popen(name, mode);
  645.     Py_END_ALLOW_THREADS
  646.     if (fp == NULL)
  647.         return amiga_error();
  648.     f = PyFile_FromFile(fp, name, mode, pclose);
  649.     if (f != NULL)
  650.         PyFile_SetBufSize(f, bufsize);
  651.     return f;
  652. }
  653. #endif
  654.  
  655. #ifdef HAVE_SETUID
  656. static PyObject *
  657. amiga_setuid(PyObject *self, PyObject *args)
  658. {
  659.     int uid;
  660. #ifdef AMITCP
  661.     if (!checkusergrouplib()) return NULL;
  662. #else
  663.     if (!checksocketlib()) return NULL;
  664. #endif
  665.     if (!PyArg_Parse(args, "i", &uid))
  666.         return NULL;
  667.     if (setuid(uid) < 0)
  668.         return amiga_error();
  669.     Py_INCREF(Py_None);
  670.     return Py_None;
  671. }
  672. #endif /* HAVE_SETUID */
  673.  
  674. #ifdef HAVE_SETGID
  675. static PyObject *
  676. amiga_setgid(PyObject *self, PyObject *args)
  677. {
  678.     int gid;
  679. #ifdef AMITCP
  680.     if (!checkusergrouplib()) return NULL;
  681. #else
  682.     if (!checksocketlib()) return NULL;
  683. #endif
  684.     if (!PyArg_Parse(args, "i", &gid))
  685.         return NULL;
  686.     if (setgid(gid) < 0)
  687.         return amiga_error();
  688.     Py_INCREF(Py_None);
  689.     return Py_None;
  690. }
  691. #endif /* HAVE_SETGID */
  692.  
  693. static PyObject *
  694. amiga_lstat(PyObject *self, PyObject *args)
  695. {
  696. #ifdef HAVE_LSTAT
  697.     return amiga_do_stat(self, args, lstat);
  698. #else /* !HAVE_LSTAT */
  699.     return amiga_do_stat(self, args, stat);
  700. #endif /* !HAVE_LSTAT */
  701. }
  702.  
  703. #ifdef HAVE_READLINK
  704. static PyObject *
  705. amiga_readlink(PyObject *self, PyObject *args)
  706. {
  707.     char buf[MAXPATHLEN];
  708.     char *path;
  709.     int n;
  710.     if (!PyArg_Parse(args, "s", &path))
  711.             return NULL;
  712.     Py_BEGIN_ALLOW_THREADS
  713.     n = readlink(path, buf, (int) sizeof buf);
  714.     Py_END_ALLOW_THREADS
  715.     if (n < 0)
  716.             return amiga_error();
  717.     return PyString_FromStringAndSize(buf, n);
  718. }
  719. #endif
  720.  
  721. #ifdef HAVE_SYMLINK
  722. static PyObject *
  723. amiga_symlink(PyObject *self, PyObject *args)
  724. {
  725.     return amiga_2str(args, symlink);
  726. }
  727. #endif
  728.  
  729. #ifdef HAVE_SETSID
  730. static PyObject *
  731. amiga_setsid(PyObject *self, PyObject *args)
  732. {
  733. #ifdef AMITCP
  734.     if (!checkusergrouplib()) return NULL;
  735. #else
  736.     if (!checksocketlib()) return NULL;
  737. #endif
  738.     if (!PyArg_Parse(args,""))
  739.         return NULL;
  740.     if ((int)setsid() < 0)
  741.         return amiga_error();
  742.     Py_INCREF(Py_None);
  743.     return Py_None;
  744. }
  745. #endif /* HAVE_SETSID */
  746.  
  747. #ifdef HAVE_SETPGID
  748. static PyObject *
  749. amiga_setpgid(PyObject *self, PyObject *args)
  750. {
  751.     int pid, pgrp;
  752.     if (!PyArg_Parse(args, "(ii)", &pid, &pgrp))
  753.         return NULL;
  754.     if (setpgid(pid, pgrp) < 0)
  755.         return amiga_error();
  756.     Py_INCREF(Py_None);
  757.     return Py_None;
  758. }
  759. #endif /* HAVE_SETPGID */
  760.  
  761. /* Functions acting on file descriptors */
  762.  
  763. static PyObject *
  764. amiga_open(PyObject *self, PyObject *args)
  765. {
  766.     char *file;
  767.     int flag;
  768.     int mode = 0777;
  769.     int fd;
  770.     if (!PyArg_Parse(args, "(si)", &file, &flag)) {
  771.         PyErr_Clear();
  772.         if (!PyArg_Parse(args, "(sii)", &file, &flag, &mode))
  773.             return NULL;
  774.     }
  775.     Py_BEGIN_ALLOW_THREADS
  776.     fd = open(file, flag, mode);
  777.     Py_END_ALLOW_THREADS
  778.     if (fd < 0)
  779.         return amiga_error();
  780.     return PyInt_FromLong((long)fd);
  781. }
  782.  
  783. static PyObject *
  784. amiga_close(PyObject *self, PyObject *args)
  785. {
  786.     int fd, res;
  787.     if (!PyArg_Parse(args, "i", &fd))
  788.         return NULL;
  789.     Py_BEGIN_ALLOW_THREADS
  790.     res = close(fd);
  791.     Py_END_ALLOW_THREADS
  792.     if (res < 0)
  793.         return amiga_error();
  794.     Py_INCREF(Py_None);
  795.     return Py_None;
  796. }
  797.  
  798. #if defined(AMITCP) || defined(INET225)
  799. static PyObject *
  800. amiga_dup(PyObject *self, PyObject *args)
  801. {
  802.     int fd;
  803.     if (!checksocketlib()) { PyErr_Clear(); errno=EIO; return amiga_error(); }
  804.     if (!PyArg_Parse(args, "i", &fd))
  805.         return NULL;
  806.     Py_BEGIN_ALLOW_THREADS
  807.     fd = dup(fd);
  808.     Py_END_ALLOW_THREADS
  809.     if (fd < 0)
  810.         return amiga_error();
  811.     return PyInt_FromLong((long)fd);
  812. }
  813.  
  814. static PyObject *
  815. amiga_dup2(PyObject *self, PyObject *args)
  816. {
  817.     int fd, fd2, res;
  818.     if (!checksocketlib()) { PyErr_Clear(); errno=EIO; return amiga_error(); }
  819.     if (!PyArg_Parse(args, "(ii)", &fd, &fd2))
  820.         return NULL;
  821.     Py_BEGIN_ALLOW_THREADS
  822.     res = dup2(fd, fd2);
  823.     Py_END_ALLOW_THREADS
  824.     if (res < 0)
  825.         return amiga_error();
  826.     Py_INCREF(Py_None);
  827.     return Py_None;
  828. }
  829. #endif
  830.  
  831. static PyObject *
  832. amiga_lseek(PyObject *self, PyObject *args)
  833. {
  834.     int fd, how;
  835.     long pos, res;
  836.     if (!PyArg_Parse(args, "(ili)", &fd, &pos, &how))
  837.         return NULL;
  838. #ifdef SEEK_SET
  839.     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
  840.     switch (how) {
  841.     case 0: how = SEEK_SET; break;
  842.     case 1: how = SEEK_CUR; break;
  843.     case 2: how = SEEK_END; break;
  844.     }
  845. #endif /* SEEK_END */
  846.     Py_BEGIN_ALLOW_THREADS
  847.     res = lseek(fd, pos, how);
  848.     Py_END_ALLOW_THREADS
  849.     if (res < 0)
  850.         return amiga_error();
  851.     return PyInt_FromLong(res);
  852. }
  853.  
  854. static PyObject *
  855. amiga_read(PyObject *self, PyObject *args)
  856. {
  857.     int fd, size;
  858.     PyObject *buffer;
  859.     if (!PyArg_Parse(args, "(ii)", &fd, &size))
  860.         return NULL;
  861.     buffer = PyString_FromStringAndSize((char *)NULL, size);
  862.     if (buffer == NULL)
  863.         return NULL;
  864.     Py_BEGIN_ALLOW_THREADS
  865.     size = read(fd, PyString_AsString(buffer), size);
  866.     Py_END_ALLOW_THREADS
  867.     if (size < 0) {
  868.         Py_DECREF(buffer);
  869.         return amiga_error();
  870.     }
  871.     _PyString_Resize(&buffer, size);
  872.     return buffer;
  873. }
  874.  
  875. static PyObject *
  876. amiga_write(PyObject *self, PyObject *args)
  877. {
  878.     int fd, size;
  879.     char *buffer;
  880.     if (!PyArg_Parse(args, "(is#)", &fd, &buffer, &size))
  881.         return NULL;
  882.     Py_BEGIN_ALLOW_THREADS
  883.     size = write(fd, buffer, size);
  884.     Py_END_ALLOW_THREADS
  885.     if (size < 0)
  886.         return amiga_error();
  887.     return PyInt_FromLong((long)size);
  888. }
  889.  
  890. static PyObject *
  891. amiga_fstat(PyObject *self, PyObject *args)
  892. {
  893.     int fd;
  894.     struct stat st;
  895.     int res;
  896.     if (!PyArg_Parse(args, "i", &fd))
  897.         return NULL;
  898.     Py_BEGIN_ALLOW_THREADS
  899.     res = fstat(fd, &st);
  900.     Py_END_ALLOW_THREADS
  901.     if (res != 0)
  902.         return amiga_error();
  903.     return Py_BuildValue("(llllllllll)",
  904.             (long)st.st_mode,
  905.             (long)st.st_ino,
  906.             (long)st.st_dev,
  907.             (long)st.st_nlink,
  908.             (long)st.st_uid,
  909.             (long)st.st_gid,
  910.             (long)st.st_size,
  911.             (long)st.st_atime,
  912.             (long)st.st_mtime,
  913.             (long)st.st_ctime);
  914. }
  915.  
  916. static PyObject *
  917. amiga_fdopen(PyObject *self, PyObject *args)
  918. {
  919.     int fd;
  920.     char *mode = "r";
  921.     int bufsize = -1;
  922.     FILE *fp;
  923.     PyObject *f;
  924.     if (!PyArg_ParseTuple(args, "i|si", &fd, &mode, &bufsize))
  925.         return NULL;
  926.     Py_BEGIN_ALLOW_THREADS
  927.     fp = fdopen(fd, mode);
  928.     Py_END_ALLOW_THREADS
  929.     if (fp == NULL)
  930.         return amiga_error();
  931.     f = PyFile_FromFile(fp, "(fdopen)", mode, fclose);
  932.     if (f != NULL)
  933.         PyFile_SetBufSize(f, bufsize);
  934.     return f;
  935. }
  936.  
  937. #if 0
  938. /*** XXX pipe() is useless without fork() or threads ***/
  939. /***     TODO: guess what.. implement threads! ***/
  940. static int pipe(int *fildes)
  941. {
  942.     /* 0=ok, -1=err, errno=EMFILE,ENFILE,EFAULT */
  943.     char buf[50];
  944.     static int num = 1;
  945.     
  946.     sprintf(buf,"PIPE:Py%ld_%ld",FindTask(0),num++);
  947.     fildes[0]=open(buf,O_RDONLY,0);
  948.     if(fildes[0]>0)
  949.     {
  950.         fildes[1]=open(buf,O_WRONLY|O_CREAT,FIBF_OTR_READ|FIBF_OTR_WRITE);
  951.         if(fildes[1]>0)
  952.         {
  953.             return 0;
  954.         }
  955.         close(fildes[0]);
  956.     }
  957.     return -1;
  958. }
  959.  
  960. static PyObject *
  961. amiga_pipe(PyObject *self, PyObject *args)
  962. {
  963.     int fds[2];
  964.     int res;
  965.     if (!PyArg_Parse(args, ""))
  966.         return NULL;
  967.     Py_BEGIN_ALLOW_THREADS
  968.     res = pipe(fds);
  969.     Py_END_ALLOW_THREADS
  970.     if (res != 0)
  971.         return amiga_error();
  972.     return Py_BuildValue("(ii)", fds[0], fds[1]);
  973. }
  974. #endif
  975.  
  976.  
  977. static PyObject *
  978. amiga_fullpath(PyObject *self, PyObject *args)
  979. {
  980.     BOOL ok=FALSE;
  981.     BPTR lk;
  982.     char *path;
  983.     char buf[MAXPATHLEN];
  984.  
  985.     if (!PyArg_ParseTuple(args, "s", &path)) return NULL;
  986.  
  987.     Py_BEGIN_ALLOW_THREADS
  988.     if(lk=Lock(path,SHARED_LOCK))
  989.     {
  990.         ok=NameFromLock(lk,buf,sizeof(buf));
  991.         UnLock(lk);
  992.     }
  993.     Py_END_ALLOW_THREADS
  994.  
  995.     if(!ok)
  996.     {
  997.         errno=__io2errno(_OSERR=IoErr());
  998.         return amiga_error();
  999.     }
  1000.     else return PyString_FromString(buf);
  1001. }
  1002.  
  1003. static PyObject *amiga_putenv(PyObject *self, PyObject *args)
  1004. {
  1005.     char *s1, *s2;
  1006.  
  1007.     if (!PyArg_ParseTuple(args, "ss", &s1, &s2)) return NULL;
  1008.     if(setenv(s1,s2,1))
  1009.     {
  1010.         amiga_error(); return NULL;
  1011.     }
  1012.     
  1013.     Py_INCREF(Py_None); return Py_None;
  1014. }
  1015.  
  1016. #ifdef HAVE_STRERROR
  1017. static char posix_strerror__doc__[] =
  1018. "strerror(code) -> string\n\
  1019. Translate an error code to a message string.";
  1020.  
  1021. PyObject *
  1022. amiga_strerror(PyObject *self, PyObject *args)
  1023. {
  1024.     int code;
  1025.     char *message;
  1026.     if (!PyArg_ParseTuple(args, "i", &code))
  1027.         return NULL;
  1028.     message = strerror(code);
  1029.     if (message == NULL) {
  1030.         PyErr_SetString(PyExc_ValueError,
  1031.                 "strerror code out of range");
  1032.         return NULL;
  1033.     }
  1034.     return PyString_FromString(message);
  1035. }
  1036. #endif /* strerror */
  1037.  
  1038. // external function prototype:
  1039. unsigned long __asm CalcCRC32(register __a1 const void *data, register __d1 unsigned long size);
  1040.  
  1041. PyObject *
  1042. amiga_crc32(PyObject *self, PyObject *args)
  1043. {
  1044.     PyObject *py_str;
  1045.     if(!PyArg_ParseTuple(args,"S",&py_str)) return NULL;
  1046.     return PyInt_FromLong(CalcCRC32(PyString_AsString(py_str), PyString_Size(py_str)));
  1047. }
  1048.  
  1049.  
  1050. static struct PyMethodDef amiga_methods[] = {
  1051.     {"chdir",   amiga_chdir},
  1052.     {"chmod",   amiga_chmod},
  1053. #ifdef HAVE_CHOWN
  1054.     {"chown",   amiga_chown},
  1055. #endif
  1056. #ifdef HAVE_GETCWD
  1057.     {"getcwd",  amiga_getcwd},
  1058. #endif
  1059.     {"fullpath", amiga_fullpath,1},
  1060. #ifdef HAVE_LINK
  1061.     {"link",    amiga_link},
  1062. #endif
  1063.     {"listdir", amiga_listdir},
  1064.     {"lstat",   amiga_lstat},
  1065.     {"mkdir",   amiga_mkdir , 1},
  1066. #ifdef HAVE_READLINK
  1067.     {"readlink",    amiga_readlink},
  1068. #endif
  1069.     {"rename",  amiga_rename},
  1070.     {"rmdir",   amiga_rmdir},
  1071.     {"stat",    amiga_stat},
  1072. #ifdef HAVE_SYMLINK
  1073.     {"symlink", amiga_symlink},
  1074. #endif
  1075. #ifdef HAVE_SYSTEM
  1076.     {"system",  amiga_system},
  1077. #endif
  1078. #if defined(AMITCP) || defined(INET225)
  1079.     {"umask",   amiga_umask},
  1080. #endif
  1081. #ifdef HAVE_UNAME
  1082.     {"uname",   amiga_uname},
  1083. #endif
  1084.     {"unlink",  amiga_unlink},
  1085.     {"remove",  amiga_unlink},
  1086. #if defined(AMITCP) || defined(INET225)
  1087.     {"utime",   amiga_utime},
  1088. #endif
  1089. #ifdef HAVE_TIMES
  1090.     {"times",   amiga_times},
  1091. #endif
  1092. #ifdef HAVE_EXECV
  1093.     {"execv",    amiga_execv},
  1094.     {"execve",    amiga_execve},
  1095. #endif /* HAVE_EXECV */
  1096. #ifdef HAVE_GETEGID
  1097.     {"getegid", amiga_getegid},
  1098. #endif
  1099. #ifdef HAVE_GETEUID
  1100.     {"geteuid", amiga_geteuid},
  1101. #endif
  1102. #ifdef HAVE_GETGID
  1103.     {"getgid",  amiga_getgid},
  1104. #endif
  1105.     {"getpid",  amiga_getpid},
  1106. #ifdef HAVE_GETPGRP
  1107.     {"getpgrp", amiga_getpgrp},
  1108. #endif
  1109. #ifdef HAVE_GETPPID
  1110.     {"getppid", amiga_getppid},
  1111. #endif
  1112. #ifdef HAVE_GETUID
  1113.     {"getuid",  amiga_getuid},
  1114. #endif
  1115. #ifdef HAVE_POPEN
  1116.     {"popen",   amiga_popen,    1},
  1117. #endif
  1118. #ifdef HAVE_SETUID
  1119.     {"setuid",  amiga_setuid},
  1120. #endif
  1121. #ifdef HAVE_SETGID
  1122.     {"setgid",  amiga_setgid},
  1123. #endif
  1124. #ifdef HAVE_SETPGRP
  1125.     {"setpgrp", amiga_setpgrp},
  1126. #endif
  1127. #ifdef HAVE_SETSID
  1128.     {"setsid",  amiga_setsid},
  1129. #endif
  1130. #ifdef HAVE_SETPGID
  1131.     {"setpgid", amiga_setpgid},
  1132. #endif
  1133. #ifdef HAVE_TCGETPGRP
  1134.     {"tcgetpgrp",   amiga_tcgetpgrp},
  1135. #endif
  1136. #ifdef HAVE_TCSETPGRP
  1137.     {"tcsetpgrp",   amiga_tcsetpgrp},
  1138. #endif
  1139.     {"open",    amiga_open},
  1140.     {"close",   amiga_close},
  1141. #if defined(AMITCP) || defined(INET225)
  1142.     {"dup",     amiga_dup},
  1143.     {"dup2",    amiga_dup2},
  1144. #endif
  1145.     {"lseek",   amiga_lseek},
  1146.     {"read",    amiga_read},
  1147.     {"write",   amiga_write},
  1148.     {"fstat",   amiga_fstat},
  1149.     {"fdopen",  amiga_fdopen,   1},
  1150. #ifdef HAVE_MKFIFO
  1151.     {"mkfifo",    amiga_mkfifo, 1},
  1152. #endif
  1153. #ifdef HAVE_FTRUNCATE
  1154.     {"ftruncate",    amiga_ftruncate, 1},
  1155. #endif
  1156. #ifdef HAVE_PUTENV
  1157.     {"putenv", amiga_putenv, 1},
  1158. #endif
  1159. #ifdef HAVE_STRERROR
  1160.     {"strerror",    amiga_strerror, 1},
  1161. #endif
  1162. #if 0
  1163.     /* XXX TODO: implement threads. Otherwise pipe() is useless. */
  1164.     {"pipe",    amiga_pipe},
  1165. #endif
  1166.     {"crc32",    amiga_crc32, 1},
  1167.     {NULL,      NULL}        /* Sentinel */
  1168. };
  1169.  
  1170.  
  1171. static int
  1172. ins(PyObject *d, char *symbol, long value)
  1173. {
  1174.         PyObject* v = PyInt_FromLong(value);
  1175.         if (!v || PyDict_SetItemString(d, symbol, v) < 0)
  1176.                 return -1;                   /* triggers fatal error */
  1177.  
  1178.         Py_DECREF(v);
  1179.         return 0;
  1180. }
  1181.  
  1182. static int all_ins(PyObject *d)
  1183. {
  1184. #ifdef WNOHANG
  1185.         if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
  1186. #endif        
  1187. #ifdef O_RDONLY
  1188.         if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
  1189. #endif
  1190. #ifdef O_WRONLY
  1191.         if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
  1192. #endif
  1193. #ifdef O_RDWR
  1194.         if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
  1195. #endif
  1196. #ifdef O_NDELAY
  1197.         if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
  1198. #endif
  1199. #ifdef O_NONBLOCK
  1200.         if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
  1201. #endif
  1202. #ifdef O_APPEND
  1203.         if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
  1204. #endif
  1205. #ifdef O_DSYNC
  1206.         if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
  1207. #endif
  1208. #ifdef O_RSYNC
  1209.         if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
  1210. #endif
  1211. #ifdef O_SYNC
  1212.         if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
  1213. #endif
  1214. #ifdef O_NOCTTY
  1215.         if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
  1216. #endif
  1217. #ifdef O_CREAT
  1218.         if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
  1219. #endif
  1220. #ifdef O_EXCL
  1221.         if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
  1222. #endif
  1223. #ifdef O_TRUNC
  1224.         if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
  1225. #endif
  1226. #ifdef O_BINARY
  1227.         if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
  1228. #endif
  1229. #ifdef O_TEXT
  1230.         if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
  1231. #endif
  1232.  
  1233. #if defined(PYOS_OS2)
  1234.         if (insertvalues(d)) return -1;
  1235. #endif
  1236.         return 0;
  1237. }
  1238.  
  1239. void
  1240. initamiga(void)
  1241. {
  1242.     PyObject *m, *d, *globv, *locv, *bothv, *aliases;
  1243.  
  1244.     m = Py_InitModule("amiga", amiga_methods);
  1245.     d = PyModule_GetDict(m);
  1246.     
  1247.     /* Initialize amiga.environ dictionary */
  1248.     if(!convertenviron(&globv, &locv, &bothv, &aliases))
  1249.         Py_FatalError("can't read environment");
  1250.  
  1251.     if (PyDict_SetItemString(d, "environ", bothv) != 0)
  1252.         Py_FatalError("can't define amiga.environ");
  1253.     Py_DECREF(bothv);
  1254.     if (PyDict_SetItemString(d, "globalvars", globv) != 0)
  1255.         Py_FatalError("can't define amiga.globalvars");
  1256.     Py_DECREF(globv);
  1257.     if (PyDict_SetItemString(d, "shellvars", locv) != 0)
  1258.         Py_FatalError("can't define amiga.shellvars");
  1259.     Py_DECREF(locv);
  1260.     if (PyDict_SetItemString(d, "shellaliases", aliases ) != 0)
  1261.         Py_FatalError("can't define amiga.shellaliases");
  1262.     Py_DECREF(aliases);
  1263.  
  1264.     if(all_ins(d)) return;
  1265.  
  1266.     /* Initialize exception */
  1267.     AmigaError = PyErr_NewException("os.error", NULL, NULL);
  1268.     if (AmigaError != NULL)
  1269.         PyDict_SetItemString(d, "error", AmigaError);
  1270. }
  1271.